﻿#include "widget.h"
#include <QtMath>

Widget::Widget(QWidget *parent)
    : QOpenGLWidget(parent)
    , VBO(QOpenGLBuffer::VertexBuffer)
    , texture(QOpenGLTexture::Target2D)
    , texture1(QOpenGLTexture::Target2D)
{
    vertices =
    {
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
        0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
        0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
        0.5f, -0.5f,  0.5f,  1.0f, 1.0f,
        0.5f, -0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };
    timer.setInterval(18);
    connect(&timer, &QTimer::timeout, this, static_cast<void (Widget::*)()>(&Widget::update));
    timer.start();
}

Widget::~Widget()
{
}

void Widget::initializeGL()
{
    initializeOpenGLFunctions();        //初始化opengl函数
    if(!shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/triangle.vert"))     //添加并编译顶点着色器
    {
        qDebug() << "ERROR:" << shaderProgram.log(); //如果编译出错,打印报错信息
    }
    if(!shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/triangle.frag"))   //添加并编译片段着色器
    {
        qDebug() << "ERROR:" << shaderProgram.log(); //如果编译出错,打印报错信息
    }
    if(!shaderProgram.link())                       //链接着色器
    {
        qDebug() << "ERROR:" << shaderProgram.log(); //如果链接出错,打印报错信息
    }

    QOpenGLVertexArrayObject::Binder{&VAO};

    VBO.create();       //生成VBO对象
    VBO.bind();         //将VBO绑定到当前的顶点缓冲对象（QOpenGLBuffer::VertexBuffer）中

    //将顶点数据分配到VBO中，第一个参数为数据指针，第二个参数为数据的字节长度
    VBO.allocate(vertices.data(), sizeof(float)*vertices.size());

    texture.create();
    texture.setData(QImage("../../tex/opengl.jpg").mirrored());
    texture.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
    texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
    texture.setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);

    texture1.create();
    texture1.setData(QImage("../../tex/sea.jpg").mirrored());
    texture1.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
    texture1.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
    texture1.setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);

    //设置顶点解析格式，并启用顶点
    shaderProgram.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 5);
    shaderProgram.enableAttributeArray("aPos");
    shaderProgram.setAttributeBuffer("aTexCoord", GL_FLOAT, sizeof(GLfloat) * 3, 2, sizeof(GLfloat) * 5);
    shaderProgram.enableAttributeArray("aTexCoord");

    glEnable(GL_DEPTH_TEST);
}

void Widget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);             //定义视口区域
}

void Widget::paintGL()
{
    glClearColor(0.1f, 0.5f, 0.7f, 1.0f); //设置清屏颜色
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);      //清除颜色缓存

    shaderProgram.bind();                     //使用shaderProgram着色程序
    {

        float time = QTime::currentTime().msecsSinceStartOfDay() / 1000.0;
        QMatrix4x4 model;
        model.rotate(180 * time, QVector3D(1.0f, 0.5f, 0.3f));
        shaderProgram.setUniformValue("model", model);

        QMatrix4x4 view;
        view.translate(0.0f, 0.0f, -3.0f);
        shaderProgram.setUniformValue("view", view);

        QMatrix4x4 projection;
        projection.perspective(45.0f, width() / (float)height(), 0.1f, 100.0f);
        shaderProgram.setUniformValue("projection", projection);

        texture.bind(0);                                    //将texture绑定到纹理单元0
        shaderProgram.setUniformValue("ourTexture", 0);     //让ourTexture从纹理单元0中获取纹理数据

        texture1.bind(1);                                    //将texture绑定到纹理单元1
        shaderProgram.setUniformValue("ourTexture1", 1);     //让ourTexture从纹理单元1中获取纹理数据

        QOpenGLVertexArrayObject::Binder{&VAO};
        glDrawArrays(GL_TRIANGLES, 0, 36);     //使用以0开始，长度为36的顶点数据来绘制三角形
    }
}
